import java.util.Scanner;

public class test1_MinOperationsToGoodString_dp {
    // 主函数：处理输入输出
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String s = scanner.next(); // 读取输入的01字符串
        System.out.println(minOperations(s)); // 输出转换为好串的最小操作次数
    }

    // 核心方法：计算将字符串转换为好串所需的最小操作次数
    private static int minOperations(String s) {
        int n = s.length();
        // 若字符串长度不足3，无法形成非法子串，直接返回0
        if (n < 3) {
            return 0;
        }

        // 初始化动态规划状态数组：prevDp[a][b]表示处理完前两个字符后，前两个字符分别为a和b的最小操作次数
        int[][] prevDp = new int[2][2];
        for (int a = 0; a < 2; a++) {       // 遍历第一个字符的可能值（0或1）
            for (int b = 0; b < 2; b++) {   // 遍历第二个字符的可能值（0或1）
                // 计算将第一个字符改为a的代价：原字符等于a对应的字符则代价为0，否则为1
                int costA = (s.charAt(0) == (a == 0 ? '0' : '1')) ? 0 : 1;
                // 计算将第二个字符改为b的代价
                int costB = (s.charAt(1) == (b == 0 ? '0' : '1')) ? 0 : 1;
                prevDp[a][b] = costA + costB; // 记录前两个字符状态的总代价
            }
        }

        // 从第三个字符开始逐字符处理（动态规划主循环）
        for (int i = 2; i < n; i++) {
            // currDp[b][c]：处理到当前字符时，前两个字符为b和c的最小操作次数
            int[][] currDp = new int[2][2];
            // 初始化currDp为不可达状态（无限大）
            for (int a = 0; a < 2; a++) {
                for (int b = 0; b < 2; b++) {
                    currDp[a][b] = Integer.MAX_VALUE;
                }
            }
            char currentChar = s.charAt(i); // 当前处理的字符的原始值

            // 遍历前两个字符的当前状态组合（a和b）
            for (int a = 0; a < 2; a++) {
                for (int b = 0; b < 2; b++) {
                    if (prevDp[a][b] == Integer.MAX_VALUE) {
                        continue; // 若之前状态无效，跳过（无法转移到新状态）
                    }
                    // 枚举当前字符的修改值c（0或1）
                    for (int c = 0; c < 2; c++) {
                        // 检查三元组（a,b,c）是否形成非法子串"010"或"101"
                        if ((a == 0 && b == 1 && c == 0) || (a == 1 && b == 0 && c == 1)) {
                            continue; // 若非法，跳过此状态
                        }
                        // 计算将当前字符改为c的代价（原字符等于目标字符时代价为0，否则为1）
                        int cost = (currentChar == (c == 0 ? '0' : '1')) ? 0 : 1;
                        // 当前总代价 = 累积的代价 + 当前字符修改的代价
                        int totalCost = prevDp[a][b] + cost;
                        // 如果新状态（b,c）的总代价更优，则更新currDp
                        if (totalCost < currDp[b][c]) {
                            currDp[b][c] = totalCost;
                        }
                    }
                }
            }
            prevDp = currDp; // 状态转移：currDp成为下一轮的prevDp
        }

        // 遍历最终所有可能的状态，找出最小操作次数
        int min = Integer.MAX_VALUE;
        for (int a = 0; a < 2; a++) {
            for (int b = 0; b < 2; b++) {
                if (prevDp[a][b] < min) {
                    min = prevDp[a][b];
                }
            }
        }
        return min; // 返回全局最小代价
    }
}

